#include <iostream>
#include <sys/ipc.h>
#include "myh/MyLog.hpp"
#include <sys/shm.h>
#include <cstring>

template <class T>
class SharedMemory
{
#define PATHNAME "/home/pst/review-linux/linux17"
#define MODE 0664
#define KEY_ID 124
#define SIZE 4096
public:
    SharedMemory(const char* pathname = PATHNAME,int keyid = KEY_ID)  
        :_shared_memory(nullptr)
        ,_shm_info(new shmid_ds)
    {
        key_t key = ftok(pathname,keyid);
        if(key < 0)
        {
            lg(Error,"[%s-%d-ftok][ftok fail:%s]",__FILE__,__LINE__,strerror(errno));
            exit(errno);
        }
        _key = key;
        printf("key:0x%x/n",_key);
    }
    ~SharedMemory()
    {
        shmdt(_shared_memory);
        if(_shm_info->shm_nattch == 1)//加锁
        {
            shmctl(_shmid,IPC_RMID,nullptr);
        }
    }


    T* GrtSharedMemory()
    {
        _shared_memory = (T*)shmat(_shmid,nullptr,0);
        if(_shared_memory < (T*)0)
        {
            lg(Error,"[%s-%d-shmat][shmat fail:%s]",__FILE__,__LINE__,strerror(errno));
            exit(errno);
        }
        return _shared_memory;
    }
    int CreShmid(const size_t size = SIZE)
    {
        int _shmid = shmget(_key,size,IPC_CREAT|IPC_EXCL|MODE);
        if(_shmid < 0)
        {
            lg(Error,"[%s-%d-shmget][shmget fail:%s]",__FILE__,__LINE__,strerror(errno));
            exit(errno);
        }  
        //CreShmidDs();
        return _shmid;
    }

    int GetShmid()
    {
        int _shmid = shmget(_key,0,0);
        if(_shmid < 0)
        {
            lg(Error,"[%s-%d-shmget][shmget fail:%s]",__FILE__,__LINE__,strerror(errno));
            exit(errno);
        }    
        //CreShmidDs();
        return _shmid;
    }
    shmid_ds& GetShmidDs(){return *_shm_info;}
private:
    void CreShmidDs()
    {
        if(shmctl(_shmid,IPC_STAT,_shm_info) < 0)
        {
            lg(Error,"[%s-%d-shmctl][shmctl fail:%s]",__FILE__,__LINE__,strerror(errno));
            exit(errno);
        }  
    }    

    T* _shared_memory;
    key_t _key;
    int _shmid;
    shmid_ds* _shm_info;
};